import java.util.*;

public class SolverStep {
	private Board board;
	private int x, y;
	private Iterator it;
	private boolean solved;
	private int depth = 0;
	final int SIZE = Board.SIZE;
	
	public SolverStep(Board b)
	{
		board = b;
		x = -1;
		y = 0;
		depth = 0;
		solved = false;
	}

	public boolean isSolved()
	{
		return solved;
	}
	
	public Board getBoard() 
	{
		return board;
	}
	
	public boolean advance()
	{
    	// search for next cell in sequence
    	x ++;
    	if (x >= SIZE) {
    		x = 0;
    		y ++;
    		if (y >= SIZE) {
    			y = 0;
    			depth ++;
    		}
    	}
		if (depth > SIZE)
			return false;
    	return true;
	}

	public synchronized SolverStep iterate()
	{
        solved = true;
        if (it != null && !it.hasNext()) {
        	// failed to find a solution on current iterator
        	return null;
        }
        while (it == null || !it.hasNext()) {
        	if (!advance()) {
    			// no more missing spaces, solution found!
        		System.out.println("I'm not sure this should happen (ran out of board space)");
        		return this;
        	}
        	if (solved && depth > 1)
        		//solution found!
        		return this;
            Cell c = board.getCell(x, y);
            if (c.getValue() <= 0) {
            	solved = false;
            	if (c.howManyPossible() <= depth) {
	                if (depth == 0)
	                    // found a cell with no valid solutions
	                    return null;
	                else
	                	it = c.iterator();
            	}
            }
        }
        
        if (it == null) {
        	System.out.println("This should not be reached! (null iterator found)");
        }
        
    	// find a number to try
        if (!it.hasNext()) {
        	System.out.println("null iterator in SolverStep.iterate()");
        	return null;
        }
       	int i = ((Integer)it.next()).intValue();
        Board tryboard = new Board(board);
        tryboard.setCellValue(x, y, i);
        return new SolverStep(tryboard);
	}
}
